package GUI;

import java.awt.Color;
import java.awt.Dialog.ModalityType;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JOptionPane;

import Verwaltung.Daten.Aktivitaet;
import Verwaltung.Daten.Interfaces.IAktivitaet;
import Verwaltung.Daten.Interfaces.IKlasse;
import Verwaltung.Daten.Interfaces.ILehrkraft;
import Verwaltung.Rechtecontroler.PermissionException;
import Verwaltung.Rechtecontroler.Rechtecontroler;

/**
 * 
 * @author MaximumDataOverdrive
 * 
 */
public class StundenplanController {

	private final Rechtecontroler rechteController = new Rechtecontroler();

	private StundenplanerFrame frame = null;

	private static StundenplanController controller = null;

	private final List<String> woche = new ArrayList<String>(Arrays.asList("",
			"Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag"));

	/**
	 * Konstruktor der den StundenplanController setzt und dabei die
	 * StundenplanerFrame lädt, updated und damit sozusagen die GUI startet.
	 */
	private StundenplanController() {

		controller = this;

		frame = new StundenplanerFrame();

		update();

		frame.setVisible(true);
	}

	/**
	 * Diese Methode aktualisert die Einträge in den
	 * Elementen(TextFeldern,Comboboxen etc.) der GUI und lädt diese dabei neu
	 * aus der Datenbank.
	 */
	public void update() {

		final Object selected = frame.getLehrerKlassenComboBox()
				.getSelectedItem();

		final DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();

		try {
			for (final IKlasse klasse : rechteController.getAlleKlassen()) {

				model.addElement(klasse.getName());
			}

			if (rechteController.getLoginlevel() >= 1) {

				for (final ILehrkraft lehrer : rechteController
						.getAlleLehrkraefte()) {

					model.addElement(lehrer.getLoginName());
				}

			} else if (rechteController.getLoginlevel() >= 0) {

				model.addElement(rechteController.getEingeloggtenNutzer()
						.getLoginName());
			}

			frame.getLehrerKlassenComboBox().setModel(model);

			if (selected != null) {

				frame.getLehrerKlassenComboBox().setSelectedItem(selected);
			}

			// sichtbarkeiten

			frame.getBtnDrucken().setVisible(
					rechteController.getLoginlevel() >= 0);

			if (rechteController.getLoginlevel() <= -1) {

				frame.getSeitenPanel().removeAll();
				final LoginPanel panel = new LoginPanel();
				frame.getSeitenPanel().add(panel);
			} else if (rechteController.getLoginlevel() == 0) {

				frame.getSeitenPanel().removeAll();
				final EigeneUebersichtPanel panel = new EigeneUebersichtPanel();
				final ILehrkraft lehrkraft = rechteController
						.getEingeloggtenNutzer();

				int stunden = 0;
				for (final IAktivitaet activi : rechteController
						.getAlleAktivitaetenFuerLehrerUndBetreuer(lehrkraft
								.getLoginName())) {
					stunden += activi.getDauer();
				}

				panel.getLblXyBelegt().setText(
						stunden + "/" + lehrkraft.getWochenstunden()
								+ " belegt");
				if (lehrkraft.getWochenstunden() - stunden < 0) {
					panel.getLblXyBelegt().setForeground(Color.red);
				} else {
					panel.getLblXyBelegt().setForeground(Color.black);
				}

				frame.getSeitenPanel().add(panel);

			} else if (rechteController.getLoginlevel() >= 1) {

				frame.getSeitenPanel().removeAll();
				final AdminPanel panel = new AdminPanel();
				final ILehrkraft lehrkraft = rechteController
						.getEingeloggtenNutzer();
				

				int stunden = 0;
				for (final IAktivitaet activi : rechteController
						.getAlleAktivitaetenFuerLehrerUndBetreuer(lehrkraft
								.getLoginName())) {
					stunden += activi.getDauer();

				}

				panel.getLblXyBelegt().setText(
						stunden + "/" + lehrkraft.getWochenstunden()
								+ " belegt");

				if (lehrkraft.getWochenstunden() - stunden < 0) {
					panel.getLblXyBelegt().setForeground(Color.red);
				} else {
					panel.getLblXyBelegt().setForeground(Color.black);
				}

				frame.getSeitenPanel().add(panel);
			}

			updateTable();

		} catch (final PermissionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Diese Methode updated bzw. lädt die Elemente des Stundenplanes neu.
	 * Hierbei wird überprüft, was dabei in der ComboBox stehen darf, da diese
	 * nur die Pläne anzeigen darf, die das derzeitige Zugriffs-Level des
	 * eingeloggten Nutzers erlaubt.
	 */
	public void updateTable() {

		final String identifiyer = (String) frame.getLehrerKlassenComboBox()
				.getSelectedItem();

		if (identifiyer != null) {

			try {

				final List<IAktivitaet> liste = rechteController
						.getAlleAktivitaetenFuerKlasse(identifiyer);

				if (rechteController.getLoginlevel() >= 1
						|| (rechteController.getLoginlevel() >= 0 && identifiyer
								.equals(getRechteController()
										.getEingeloggtenNutzer().getLoginName()))) {
					liste.addAll(rechteController
							.getAlleAktivitaetenFuerLehrerUndBetreuer(identifiyer));
				}

				for (int tag = 1; tag <= 5; tag++) {

					for (int stunde = 8; stunde <= 15; stunde++) {

						IAktivitaet aktivi = null;

						for (final IAktivitaet ak : liste) {

							if (ak.getStartHour() == stunde
									&& ak.getWochentag()
											.toLowerCase()
											.equals(woche.get(tag)
													.toLowerCase())) {

								aktivi = ak;
							}
						}

						if (aktivi == null) {

							// create dummy
							aktivi = new Aktivitaet("", woche.get(tag), stunde,
									0, 1, true);

							frame.getTableModel().setData(stunde - 8, tag - 1,
									aktivi);
						} else {

							frame.getTableModel().setData(stunde - 8, tag - 1,
									aktivi);
						}

					}
				}

			} catch (final PermissionException e) {
				e.printStackTrace();
			}
			frame.getTableModel().fireTableDataChanged();
		}
	}

	/**
	 * Diese Methode bekommt den Login-Namen, sowie das Passwort übergeben und
	 * prüft, ob diese in der Datenbank vorhanden sind. Wenn dies nicht so sein
	 * sollte, lässt sie eine Meldung erscheinen. Nach dem Login wird der
	 * Stundenplancontroler geupdated.
	 * 
	 * @param loginname
	 *            Login-Name der Lehrkraft(oder Admin) die in der Datenbank
	 *            steht.
	 * @param password
	 *            Passwort der Lehrkraft(oder Admin) das in der Datenbank steht.
	 */
	public void einloggen(final String loginname, final String password) {

		try {
			if (!rechteController.login(loginname, password)) {

				JOptionPane.showMessageDialog(frame, "Fehler beim Login");
			}
		} catch (final Exception e) {
			JOptionPane.showMessageDialog(frame, "Fehler beim Login");
		}

		update();
	}

	/**
	 * Gibt den StundenplanController zurück und erzeugt diesen, falls er nicht
	 * vorhanden ist.
	 * 
	 * @return controller der Stundenplan-Controler
	 */
	public static StundenplanController getInstance() {

		if (controller == null) {

			controller = new StundenplanController();
		}

		return controller;
	}

	/**
	 * Launch the application.
	 */
	public static void main(final String[] args) {
		EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				try {
					getInstance();

				} catch (final Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public void setEigenPlan() {

		final String item = rechteController.getEingeloggtenNutzer()
				.getLoginName();

		frame.getLehrerKlassenComboBox().setSelectedItem(item);
		// DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>)
		// frame.getLehrerKlassenComboBox().getModel();
		//
		// for(int i = 0; i < model.getSize();i++) {
		//
		// System.out.println(model.getElementAt(i) + " " + item);
		// if(model.getElementAt(i).equals(item)) {
		//
		// frame.getLehrerKlassenComboBox().setSelectedIndex(i);
		// break;
		// }
		// }

		update();
	}

	/**
	 * Methode die den derzeitig eingeloggten User ausloggt. Sie updated danach.
	 */
	public void ausloggen() {

		if (rechteController.logout()) {

			JOptionPane.showMessageDialog(frame, "Erfolgreich ausgeloggt!");
		} else {
			JOptionPane.showMessageDialog(frame, "Fehler beim ausloggen");
		}

		update();
	}

	/**
	 * Methode die den Edit-Klassen-Dialog nutzt, um die Klassen der Frame zu
	 * updaten.
	 */
	public void updateKlassen() {

		final KlassenEditDialog dialog = new KlassenEditDialog(frame);
		dialog.pack();
		dialog.setLocationRelativeTo(null);
		dialog.setModalityType(ModalityType.APPLICATION_MODAL);
		dialog.setVisible(true);
		// update();

	}

	/**
	 * Methode die den Edit-Lehrer-Dialog nutzt, um die Lehrkräfte der Frame zu
	 * updaten.
	 */
	public void updateLehrkraefte() {

		final LehrerEditDialog dialog = new LehrerEditDialog(frame);
		dialog.pack();
		dialog.setLocationRelativeTo(null);
		dialog.setModalityType(ModalityType.APPLICATION_MODAL);
		dialog.setVisible(true);

		// update();

	}

	/**
	 * Diese Methode gibt den Rechtecontroler zurück.
	 * 
	 * @return Rechtecontroler Verwalter der Eingaben in die GUI
	 */
	public Rechtecontroler getRechteController() {
		return rechteController;
	}

	/**
	 * Diese Methode checkt, ob es zu einer Überdeckung bei den Aktivitäten
	 * einer Lehrkraft oder Klasse kommt. Dabei werden auch die Wochenstunden
	 * die eine Lehrkraft arbeiten darf geprüft.
	 * 
	 * @throws PermissionException
	 *             wird in der Rechtecontroler-Klasse geworfen
	 */
	public boolean checkUeberdeckung() throws PermissionException {

		final List<ILehrkraft> liste = rechteController.getAlleLehrkraefte();

		for (final ILehrkraft lehr : liste) {

			final List<IAktivitaet> list = rechteController
					.getAlleAktivitaetenFuerLehrerUndBetreuer(lehr
							.getLoginName());

			final int[][] abdeckung = new int[6][60 * 8];

			for (final IAktivitaet ak : list) {

				final int tagAsInt = woche.indexOf(ak.getWochentag());
				final int startzeit = ((ak.getStartHour() - 8) * 60) + ak.getStartMinute();
				for (int i = startzeit; i < ak.getDauer() + startzeit; i++) {
					abdeckung[tagAsInt][i] += 1;
				}
			}

			for (int i = 0; i < abdeckung.length; i++) {
				for (int j = 0; j < abdeckung[i].length; j++) {

					if (abdeckung[i][j] >= 2) {

						JOptionPane.showMessageDialog(frame,
								"Es gibt eine überdeckung bei der Lehrkraft: "
										+ lehr.getName() + " am " + woche.get(i) + " um " + ((j /60) + 8) + "Uhr");

						return false;
					}
				}
			}
		}

		// wochenstunden schutz

		for (final ILehrkraft lehr : liste) {

			final List<IAktivitaet> list = rechteController
					.getAlleAktivitaetenFuerLehrerUndBetreuer(lehr
							.getLoginName());

			int stundenGearbeitet = 0;

			for (final IAktivitaet ak : list) {

				stundenGearbeitet += ak.getDauer();
			}

			if (stundenGearbeitet > lehr.getWochenstunden()) {

				JOptionPane.showMessageDialog(
						frame,
						"Die Lehrkraft " + lehr.getName() + " muss nun "
								+ stundenGearbeitet
								+ " Stunden arbeiten. Wobei nur "
								+ lehr.getWochenstunden() + " erlaubt wären!");
				return false;
			}
 
		}

		// überdeckung klasse

		final List<IKlasse> klassen = rechteController.getAlleKlassen();

		for (final IKlasse klasse : klassen) {

			final List<IAktivitaet> list = rechteController
					.getAlleAktivitaetenFuerKlasse(klasse.getName());

			final int[][] abdeckung = new int[6][60 * 10];

			for (final IAktivitaet ak : list) {

				final int tagAsInt = woche.indexOf(ak.getWochentag());
				final int startzeit = ((ak.getStartHour() - 8) * 60) + ak.getStartMinute();;
				for (int i = startzeit; i < ak.getDauer() + startzeit; i++) {
					abdeckung[tagAsInt][i] += 1;
				}
			}

			for (int i = 0; i < abdeckung.length; i++) {
				for (int j = 0; j < abdeckung[i].length; j++) {

					if (abdeckung[i][j] >= 2) {

						JOptionPane.showMessageDialog(frame,
								"Es gibt eine überdeckung bei der Klasse: "
										+ klasse.getName()+ " am " + woche.get(i) + " um " + ((j /60) + 8) + "Uhr");
						return false ;
					}
				}
			}
		}

		return true;
	}
}
